//
// Created by RandBII on 2020/12/24.
//

#ifndef FFMPEGFORANDROID_DECODERBASE_H
#define FFMPEGFORANDROID_DECODERBASE_H

extern "C" {
#include <libavutil/frame.h>
#include <libavutil/time.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}

#include <thread>
#include "Decoder.h"
#include "LogUil.h"
#include "TimeHelper.h"

#define MAX_PATH 2048
// 100ms
#define DELAY_THRESHOLD 100

using namespace std;

//解码器的状态
enum DecoderState {
    STATE_DECODING,
    STATE_STOP,
    STATE_PAUSE,
    STATE_UNKNOWN
};

enum DecoderMsg {
    MSG_DECODER_INIT_ERROR,
    MSG_DECODER_READY,
    MSG_DECODER_DONE,
    MSG_DECODING_TIME,
    MSG_REQUEST_RENDER
};

//音视频的解码器基类
class DecoderBase : public Decoder {

public:
    DecoderBase() {};

    virtual ~DecoderBase() {};

    virtual void Start();

    virtual void Stop();

    virtual void Pause();

    virtual float GetDuration();

    //seek 到某个时间点播放
    virtual void SeekToPosition(float position);

    virtual void ClearCache();

    virtual void SetMessageCallback(void *context, MessageCallback messageCallback);

    virtual void SetAVSyncCallback(void *context, AVSyncCallback callback);


private :
    int InitFFDecoder();

    void UnInitFFDecoder();

    void StartDecodingThread();

    void DecodingLoop();

    void UpdateTimeStamp();

//    音视频同步信号
    long AVSync();

    int DecodeOnePacket();

//    线程函数
    static void DoAVDecoding(DecoderBase *decoder);

//封装格式上下文
    AVFormatContext *m_AVFormatContext = nullptr;
//    解码器上下文
    AVCodecContext *m_AVCodecContext = nullptr;
//解码器
    AVCodec *m_AVCodec = nullptr;

    AVPacket *m_AVPacket = nullptr;

    AVFrame *m_AVFrame = nullptr;

    AVMediaType m_MediaType = AVMEDIA_TYPE_UNKNOWN;

    char m_Url[MAX_PATH] = {0};

    long m_CurrentTimeStamp = 0;
//    播放起始时间的时间戳
    long m_StartTimeStamp = -1;
//总时长
    long m_Duration = 0;
//数据流索引
    int m_StreamIndex = -1;
//    锁、条件变量
    mutex m_Mutex;
//条件
    condition_variable m_Cond;

    thread *m_Thread = nullptr;
    volatile float m_SeekPosition = 0;
    volatile bool m_SeekSuccess = false;
    volatile int m_DecoderState = STATE_UNKNOWN;

    void *m_AVDecoderContext = nullptr;
    AVSyncCallback m_AVSyncCallback = nullptr;

protected:
    void *m_MsgContext = nullptr;
    MessageCallback m_MessageCallback = nullptr;

    virtual int Init(const char *url, AVMediaType mediaType);

    virtual void UnInit();

    virtual void OnDecoderReady() = 0;

    virtual void OnDecoderDone() = 0;

//解码数据的回调
    virtual void OnFrameAvailable(AVFrame *frame) = 0;

    AVCodecContext *GetCodecContext();
};


#endif //FFMPEGFORANDROID_DECODERBASE_H
